package org.springblade.modules.admin.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.PlanCheckStatisticsQueryDTO;
import org.springblade.modules.admin.dto.sugar.ElevatorByCollectListDTO;
import org.springblade.modules.admin.dto.sugar.SugarSearchDTO;
import org.springblade.modules.admin.entity.Elevator;
import org.springblade.modules.admin.entity.ElevatorPrincipalDept;
import org.springblade.modules.admin.entity.MaintainPlanUserDayCount;
import org.springblade.modules.admin.enums.ElevatorAuditTypeEnum;
import org.springblade.modules.admin.enums.ElevatorMaintainStatusEnums;
import org.springblade.modules.admin.enums.ElevatorScheduleLabelEnum;
import org.springblade.modules.admin.enums.TaskStatusEnum;
import org.springblade.modules.admin.service.ElevatorByCollectService;
import org.springblade.modules.admin.service.ElevatorPrincipalDeptService;
import org.springblade.modules.admin.service.IElevatorExtService;
import org.springblade.modules.admin.service.IMaintainPlanContentService;
import org.springblade.modules.admin.vo.CheckStatisticsTrendVO;
import org.springblade.modules.admin.vo.sugar.ElevatorByCollectScheduleListVO;
import org.springblade.modules.admin.vo.sugar.ElevatorByCollectVO;
import org.springblade.modules.system.service.IDeptService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@AllArgsConstructor
@Service
public class ElevatorByCollectServiceImpl implements ElevatorByCollectService {

	private final IMaintainPlanContentService planContentService;
	private final IElevatorExtService elevatorExtService;
	private final ElevatorPrincipalDeptService elevatorPrincipalDeptService;
	private final IDeptService deptService;

	@Override
	public ElevatorByCollectVO selectOverdueCount(SugarSearchDTO searchDTO) {
		// 该接口不受时间范围影响
		searchDTO.setStartDate(null);
		searchDTO.setEndDate(null);
		// 封装工单状态
		List<Integer> planStatusList = new ArrayList<>();
		planStatusList.add(TaskStatusEnum.BY_DISABLE.getStatus());
		planStatusList.add(TaskStatusEnum.BY_PROCESSED.getStatus());
		planStatusList.add(TaskStatusEnum.BY_FINISH.getStatus());
		searchDTO.setPlanStatusList(planStatusList);
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<Long> planIds = planContentService.selectElevatorByCollectPlanIds(searchDTO);
		ElevatorByCollectVO result = new ElevatorByCollectVO();
		if(Func.isNotEmpty(planIds)){
			List<ElevatorByCollectListDTO> list = planContentService.selectElevatorByCollectList(planIds);
			result.setUnfinished(list.stream().count());
			result.setOverdue(list.stream().filter(e -> e.getPlanAuditType().equals(2) && Func.isNotEmpty(e.getPlanOverdueType()) && e.getPlanOverdueType().equals(3)).count());
			result.setFutureOverdue(list.stream().filter(e -> e.getPlanAuditType().equals(2) && Func.isNotEmpty(e.getPlanOverdueType()) && e.getPlanOverdueType().equals(2)).count());
		}
		return result;
	}

	@Override
	public ElevatorByCollectVO selectOverdueRateTrend(SugarSearchDTO searchDTO) {
		ElevatorByCollectVO result = new ElevatorByCollectVO();
		Map<String,Object> trendData = this.initTrendEntiretyDay(searchDTO);
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<Long> planIds = planContentService.selectElevatorByCollectPlanIds(searchDTO);
		if(Func.isNotEmpty(planIds)){
			List<ElevatorByCollectListDTO> list = planContentService.selectElevatorByCollectList(planIds);
			long planTotal = planIds.stream().count();
			long overdue = list.stream().filter(e -> !Func.hasEmpty(e.getPlanAuditType(),e.getPlanOverdueType()) && e.getPlanAuditType().equals(2) && e.getPlanOverdueType().equals(3)).count();
			result.setOverdue(overdue);
			result.setOverdueRate(BigDecimal.valueOf(overdue).divide(BigDecimal.valueOf(planTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));

			Map<String,List<ElevatorByCollectListDTO>> dateGroup = list.stream().collect(Collectors.groupingBy(t -> DateUtil.format(t.getPlanDate(), "yyyy/M/d")));
			trendData.forEach((k,v) -> {
				if(dateGroup.containsKey(k)){
					List<ElevatorByCollectListDTO> dateList = dateGroup.get(k);
					long datePlanTotal = dateList.stream().count();
					long dateOverdue = dateList.stream().filter(e -> e.getPlanAuditType().equals(2) && Func.isNotEmpty(e.getPlanOverdueType()) && e.getPlanOverdueType().equals(3)).count();
					trendData.put(k,BigDecimal.valueOf(dateOverdue).divide(BigDecimal.valueOf(datePlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
				}
			});
		}
		result.setTrendData(trendData);
		return result;
	}

	@Override
	public ElevatorByCollectVO selectTimelinessRateTrend(SugarSearchDTO searchDTO) {
		ElevatorByCollectVO result = new ElevatorByCollectVO();
		Map<String,Object> trendData = this.initTrendEntiretyDay(searchDTO);
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<Long> planIds = planContentService.selectElevatorByCollectPlanIds(searchDTO);
		if(Func.isNotEmpty(planIds)){
			List<ElevatorByCollectListDTO> list = planContentService.selectElevatorByCollectList(planIds);
			List<Integer> planStatusList = new ArrayList<>();
			planStatusList.add(TaskStatusEnum.BY_SIGN.getStatus());
			planStatusList.add(TaskStatusEnum.BY_MAINTAIN_SIGN.getStatus());
			searchDTO.setPlanStatusList(planStatusList);
			long planTotal = planIds.stream().count();
			long inTime = list.stream().filter(e -> planStatusList.contains(e.getPlanStatus()) && DateUtil.compare(e.getPlanDate(),e.getMaintainSignatureTime(),"yyyy-MM-dd") >= 0).count();
			result.setInTime(inTime);
			result.setInTimeRate(BigDecimal.valueOf(inTime).divide(BigDecimal.valueOf(planTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));

			Map<String,List<ElevatorByCollectListDTO>> dateGroup = list.stream().collect(Collectors.groupingBy(t -> DateUtil.format(t.getPlanDate(), "yyyy/M/d")));
			trendData.forEach((k,v) -> {
				if(dateGroup.containsKey(k)){
					List<ElevatorByCollectListDTO> dateList = dateGroup.get(k);
					long datePlanTotal = dateList.stream().count();
					long dateOverdue = dateList.stream().filter(e -> planStatusList.contains(e.getPlanStatus()) && DateUtil.compare(e.getPlanDate(),e.getMaintainSignatureTime(),"yyyy-MM-dd") >= 0).count();
					trendData.put(k,BigDecimal.valueOf(dateOverdue).divide(BigDecimal.valueOf(datePlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
				}
			});
		}
		result.setTrendData(trendData);
		return result;
	}

	@Override
	public ElevatorByCollectVO selectWorkTimeAveTrend(SugarSearchDTO searchDTO) {
		ElevatorByCollectVO result = new ElevatorByCollectVO();
		Map<String,Object> trendData = this.initTrendEntiretyDay(searchDTO);
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<Long> planIds = planContentService.selectElevatorByCollectPlanIds(searchDTO);
		if(Func.isNotEmpty(planIds)){
			List<ElevatorByCollectListDTO> list = planContentService.selectElevatorByCollectList(planIds);
			long planTotal = list.stream().filter(e -> Func.isNotEmpty(e.getWorkDuration())).count();
			int workDuration = list.stream().filter(e -> Func.isNotEmpty(e.getWorkDuration())).mapToInt(ElevatorByCollectListDTO::getWorkDuration).sum();
			if(workDuration > 0){
				result.setWorkTimeAve(BigDecimal.valueOf(workDuration).divide(BigDecimal.valueOf(planTotal),1, RoundingMode.HALF_UP));
			}

			Map<String,List<ElevatorByCollectListDTO>> dateGroup = list.stream().collect(Collectors.groupingBy(t -> DateUtil.format(t.getPlanDate(), "yyyy/M/d")));
			trendData.forEach((k,v) -> {
				if(dateGroup.containsKey(k)){
					List<ElevatorByCollectListDTO> dateList = dateGroup.get(k);
					long datePlanTotal = dateList.stream().filter(e -> Func.isNotEmpty(e.getWorkDuration())).count();
					int dateWorkDuration = dateList.stream().filter(e -> Func.isNotEmpty(e.getWorkDuration())).mapToInt(ElevatorByCollectListDTO::getWorkDuration).sum();
					if(datePlanTotal > 0){
						trendData.put(k,BigDecimal.valueOf(dateWorkDuration).divide(BigDecimal.valueOf(datePlanTotal),1, RoundingMode.HALF_UP));
					}
				}
			});
		}
		result.setTrendData(trendData);
		return result;
	}

	@Override
	public ElevatorByCollectVO selectByCorrelationZgTrend(SugarSearchDTO searchDTO) {
		ElevatorByCollectVO result = new ElevatorByCollectVO();
		Map<String,Object> trendData = this.initTrendEntiretyDay(searchDTO);
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<Long> planIds = planContentService.selectElevatorByCollectPlanIds(searchDTO);
		if(Func.isNotEmpty(planIds)){
			List<ElevatorByCollectListDTO> list = planContentService.selectElevatorByCollectCorrelationZgList(planIds);
			long correlationZg = list.stream().filter(e -> Func.isNotEmpty(e.getZgPlanId())).map(ElevatorByCollectListDTO::getPlanId).distinct().count();
			result.setCorrelationZg(correlationZg);
			long scorePlanTotal = list.stream().filter(e -> Func.isNotEmpty(e.getPlanScoreStatus()) && e.getPlanScoreStatus() == 1).map(ElevatorByCollectListDTO::getPlanId).distinct().count();
			long scoreZgTotal = list.stream().filter(e -> Func.isNotEmpty(e.getPlanScoreStatus()) && e.getPlanScoreStatus() == 1 && Func.isNotEmpty(e.getZgPlanId())).map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
			if(scorePlanTotal > 0){
				result.setCorrelationZgRate(BigDecimal.valueOf(scoreZgTotal).divide(BigDecimal.valueOf(scorePlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
			}

			Map<String,List<ElevatorByCollectListDTO>> dateGroup = list.stream().collect(Collectors.groupingBy(t -> DateUtil.format(t.getPlanDate(), "yyyy/M/d")));
			trendData.forEach((k,v) -> {
				if(dateGroup.containsKey(k)){
					List<ElevatorByCollectListDTO> dateList = dateGroup.get(k);
					long dateScorePlanTotal = dateList.stream().filter(e -> Func.isNotEmpty(e.getPlanScoreStatus()) && e.getPlanScoreStatus() == 1).map(ElevatorByCollectListDTO::getPlanId).distinct().count();
					long dateScoreZgTotal = dateList.stream().filter(e -> Func.isNotEmpty(e.getPlanScoreStatus()) && e.getPlanScoreStatus() == 1 && Func.isNotEmpty(e.getZgPlanId())).map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
					if(dateScorePlanTotal > 0){
						trendData.put(k,BigDecimal.valueOf(dateScoreZgTotal).divide(BigDecimal.valueOf(dateScorePlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
					}
				}
			});
		}
		result.setTrendData(trendData);
		return result;
	}

	@Override
	public ElevatorByCollectVO selectByCorrelationZgStatusTrend(SugarSearchDTO searchDTO) {
		ElevatorByCollectVO result = new ElevatorByCollectVO();
		Map<String,Object> trendData = this.initTrendEntiretyDay(searchDTO);
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<ElevatorByCollectListDTO> list = planContentService.selectElevatorByCollectCorrelationZgStatusList(searchDTO);
		if(Func.isNotEmpty(list)){
			long zgPlanTotal = list.stream().map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
			long zgPlanFinshedTotal = list.stream().filter(e -> e.getZgPlanStatus().equals(TaskStatusEnum.ZG_SIGN_FINISH.getStatus())).map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
			long correlationZgOnTime = list.stream().filter(e -> e.getZgPlanStatus().equals(TaskStatusEnum.ZG_SIGN_FINISH.getStatus())
				&& ((Func.isNotEmpty(e.getZgRedeployUserIds()) && e.getZgRedeployOverdueStatus().equals(1))
				|| (Func.isEmpty(e.getZgRedeployUserIds()) && e.getZgOverdueType().equals(1)))).map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
			if(zgPlanTotal > 0){
				result.setCorrelationZgFinishedRate(BigDecimal.valueOf(zgPlanFinshedTotal).divide(BigDecimal.valueOf(zgPlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
				result.setCorrelationZgOnTimeRate(BigDecimal.valueOf(correlationZgOnTime).divide(BigDecimal.valueOf(zgPlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
			}

			Map<String,List<ElevatorByCollectListDTO>> dateGroup = list.stream().collect(Collectors.groupingBy(t -> DateUtil.format(t.getZgCreateTime(), "yyyy/M/d")));
			trendData.forEach((k,v) -> {
				if(dateGroup.containsKey(k)){
					List<ElevatorByCollectListDTO> dateList = dateGroup.get(k);
					long dateZgPlanTotal = dateList.stream().map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
					long dateZgPlanFinshedTotal = dateList.stream().filter(e -> e.getZgPlanStatus().equals(TaskStatusEnum.ZG_SIGN_FINISH.getStatus())).map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
					if(dateZgPlanTotal > 0){
						trendData.put(k,BigDecimal.valueOf(dateZgPlanFinshedTotal).divide(BigDecimal.valueOf(dateZgPlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
					}
				}
			});
		}
		result.setTrendData(trendData);
		return result;
	}

	@Override
	public List<Map<String, Object>> selectScheduleLabelCountList(SugarSearchDTO searchDTO) {

		List<Map<String, Object>> resultList = new ArrayList<>();
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<Long> elevatorIds = elevatorExtService.selectElevatorIds(searchDTO);
		if(Func.isNotEmpty(elevatorIds)){
			List<ElevatorByCollectListDTO> list = elevatorExtService.selectElevatorCollectByIds(elevatorIds);
			if(Func.isNotEmpty(list)){
				List<ElevatorByCollectScheduleListVO> scheduleList = new ArrayList<>();
				ElevatorScheduleLabelEnum[] enums = ElevatorScheduleLabelEnum.values();
				for (ElevatorScheduleLabelEnum e : enums){
					if(e.getCode() != 1){
						long num = list.stream().filter(t -> Func.isNotEmpty(t.getScheduleLabel()) && Func.toIntList(t.getScheduleLabel()).contains(e.getCode())).count();
						if(num > 0){
							ElevatorByCollectScheduleListVO schedule = new ElevatorByCollectScheduleListVO();
							schedule.setCode(Long.valueOf(e.getCode()));
							schedule.setName(e.getName());
							schedule.setDesc(e.getDesc());
							schedule.setType(e.getType());
							schedule.setNum(num);
							scheduleList.add(schedule);
						}
					}
				}
				if(Func.isNotEmpty(scheduleList)){
					Map<String,List<ElevatorByCollectScheduleListVO>> typeGroup = scheduleList.stream().collect(Collectors.groupingBy(ElevatorByCollectScheduleListVO::getType));
					typeGroup.forEach((k,v) -> {
						Map<String,Object> map = new HashMap<>(2);
						map.put("name",k);
						map.put("data",v);
						resultList.add(map);
					});
				}
			}
		}

		return resultList;
	}

	@Override
	public List<ElevatorByCollectScheduleListVO> selectScheduleLabelCountChildList(SugarSearchDTO searchDTO) {
		List<ElevatorByCollectScheduleListVO> resultList = new ArrayList<>();
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<Long> elevatorIds = elevatorExtService.selectElevatorIds(searchDTO);
		if(Func.isNotEmpty(elevatorIds)){
			Integer code = searchDTO.getCode();
			List<ElevatorByCollectListDTO> list = elevatorExtService.selectElevatorCollectByScheduleLabel(elevatorIds,code);

			if(code.equals(ElevatorScheduleLabelEnum.NO_FUTURE_SCHEDULE.getCode())){
				list = list.stream().filter(e -> {
					if(Func.isNotEmpty(e.getMaintainStatus())){
						if(ElevatorMaintainStatusEnums.CONTRACT_IN_TIME.getId() == e.getMaintainStatus()){
							return Boolean.TRUE;
						}
						if(ElevatorMaintainStatusEnums.DIS_ENABLE.getId() == e.getMaintainStatus()){
							return Boolean.TRUE;
						}
						if(ElevatorMaintainStatusEnums.OUT_TIME_STOP.getId() == e.getMaintainStatus()){
							e.setMaintainStatus(ElevatorMaintainStatusEnums.CONTRACT_OUT_TIME.getId());
							return Boolean.TRUE;
						}
						if(ElevatorMaintainStatusEnums.OUT_TIME_END.getId() == e.getMaintainStatus()){
							e.setMaintainStatus(ElevatorMaintainStatusEnums.CONTRACT_OUT_TIME.getId());
							return Boolean.TRUE;
						}
						if(ElevatorMaintainStatusEnums.OUT_TIME_END_HAS_NEXT.getId() == e.getMaintainStatus()){
							e.setMaintainStatus(ElevatorMaintainStatusEnums.CONTRACT_OUT_TIME.getId());
							return Boolean.TRUE;
						}
					}
					return Boolean.FALSE;
				}).collect(Collectors.toList());
				if(Func.isNotEmpty(list)){
					Map<Integer,List<ElevatorByCollectListDTO>> maintainStatusGroup = list.stream().collect(Collectors.groupingBy(ElevatorByCollectListDTO::getMaintainStatus));
					List<ElevatorByCollectScheduleListVO> finalResultList = new ArrayList<>();
					maintainStatusGroup.forEach((k, v) -> {
						ElevatorByCollectScheduleListVO result = new ElevatorByCollectScheduleListVO();
						result.setName(ElevatorMaintainStatusEnums.getName(k));
						result.setCode(Long.valueOf(k));
						result.setNum(v.stream().count());
						List<ElevatorByCollectScheduleListVO> child = new ArrayList<>();
						List<ElevatorByCollectListDTO> userTypeList = v.stream().filter(e -> Func.isNotEmpty(e.getUseType())).collect(Collectors.toList());
						if(Func.isNotEmpty(userTypeList)){
							Map<Integer,List<ElevatorByCollectListDTO>> useTypeGroup = userTypeList.stream().collect(Collectors.groupingBy(ElevatorByCollectListDTO::getUseType));
							useTypeGroup.forEach((o1,o2) -> {
								ElevatorByCollectScheduleListVO o = new ElevatorByCollectScheduleListVO();
								o.setName(String.format("%s梯",ElevatorAuditTypeEnum.getName(o1)));
								o.setCode(Long.valueOf(o1));
								o.setNum(o2.stream().count());
								child.add(o);
							});
						}
						result.setChild(child);
						finalResultList.add(result);
					});
					resultList = finalResultList;
				}
			}

			if(code.equals(ElevatorScheduleLabelEnum.LAST_PLAN_DATE_MOVE_15_DAYS.getCode())){
				Map<Long,String> buildingGroup = list.stream().collect(Collectors.toMap(ElevatorByCollectListDTO::getBuildingId,ElevatorByCollectListDTO::getBuildingName,(k1,k2) -> k1));
				List<ElevatorByCollectListDTO> finalList = list;
				List<ElevatorByCollectScheduleListVO> finalResultList = new ArrayList<>();
				buildingGroup.forEach((k, v) -> {
					ElevatorByCollectScheduleListVO result = new ElevatorByCollectScheduleListVO();
					result.setCode(k);
					result.setName(v);
					result.setNum(finalList.stream().filter(e -> k.equals(e.getBuildingId())).count());
					finalResultList.add(result);
				});
				resultList = finalResultList.stream().sorted(Comparator.comparing(ElevatorByCollectScheduleListVO::getNum).reversed()).collect(Collectors.toList());
			}

			if(code.equals(ElevatorScheduleLabelEnum.HAS_FUTURE_SCHEDULE_AND_NO_FUTURE_CONTRACT.getCode())){
				String[] nameStr = {"合同已到期>=90天","合同已到期60~90天","合同已到期30~60天","合同已到期<30天"};
				for (String name : nameStr){
					ElevatorByCollectScheduleListVO result = new ElevatorByCollectScheduleListVO();
					if(name.equals(nameStr[0])){
						result.setCode(1L);
						result.setName(name);
						result.setNum(list.stream().filter(e -> Func.isNotEmpty(e.getContractEndTime())
							&& DateUtil.date().getTime() - e.getContractEndTime().getTime() >= 90*24*60*60*1000L).count());
					}
					if(name.equals(nameStr[1])){
						result.setCode(2L);
						result.setName(name);
						result.setNum(list.stream().filter(e -> Func.isNotEmpty(e.getContractEndTime())
							&& DateUtil.date().getTime() - e.getContractEndTime().getTime() < 90*24*60*60*1000L
							&& DateUtil.date().getTime() - e.getContractEndTime().getTime() >= 60*24*60*60*1000L
						).count());
					}
					if(name.equals(nameStr[2])){
						result.setCode(3L);
						result.setName(name);
						result.setNum(list.stream().filter(e -> Func.isNotEmpty(e.getContractEndTime())
							&& DateUtil.date().getTime() - e.getContractEndTime().getTime() < 60*24*60*60*1000L
							&& DateUtil.date().getTime() - e.getContractEndTime().getTime() >= 30*24*60*60*1000L
						).count());
					}
					if(name.equals(nameStr[3])){
						result.setCode(4L);
						result.setName(name);
						result.setNum(list.stream().filter(e -> Func.isNotEmpty(e.getContractEndTime())
							&& DateUtil.date().getTime() - e.getContractEndTime().getTime() < 30*24*60*60*1000L
						).count());
					}
					resultList.add(result);
				}
			}

			if(code.equals(ElevatorScheduleLabelEnum.MOVE_15_DAYS_SCHEDULE.getCode())){
				String[] nameStr = {"下次保养计划距上次保养超15天","剩余排期间隔存在超15天风险"};
				for (String name : nameStr){
					ElevatorByCollectScheduleListVO result = new ElevatorByCollectScheduleListVO();
					if(name.equals(nameStr[0])){
						result.setCode(1L);
						result.setName(name);
						result.setNum(list.stream().filter(e -> Func.isNotEmpty(e.getPreviousPlanDate())
							&& Func.isNotEmpty(e.getNextPlanDate())
							&& DateUtil.compare(DateUtil.offsetDay(e.getPreviousPlanDate(),15),e.getNextPlanDate(),"yyyy-MM-dd") < 0
						).count());
					}
					if(name.equals(nameStr[1])){
						result.setCode(2L);
						result.setName(name);
						result.setNum(list.stream().filter(e -> Func.isNotEmpty(e.getOtherOverdue())
							&& e.getOtherOverdue() == 1
						).count());
					}
					resultList.add(result);
				}
			}

			if(code.equals(ElevatorScheduleLabelEnum.SOLO_SCHEDULE.getCode())){
				List<ElevatorPrincipalDept> deptGroupList = elevatorPrincipalDeptService.selectDeptGroupByElevatorIds(elevatorIds);
				if(Func.isNotEmpty(deptGroupList)){
					List<ElevatorByCollectScheduleListVO> finalResultList = new ArrayList<>();
					List<ElevatorByCollectListDTO> finalList = list;
					deptGroupList.forEach(e -> {
						long num = finalList.stream().filter(t -> e.getElevatorIds().contains(String.valueOf(t.getElevatorId()))).count();
						if(num > 0){
							ElevatorByCollectScheduleListVO result = new ElevatorByCollectScheduleListVO();
							result.setCode(e.getDeptId());
							result.setName(e.getDeptName());
							result.setNum(num);
							finalResultList.add(result);
						}
					});
					resultList = finalResultList.stream().sorted(Comparator.comparing(ElevatorByCollectScheduleListVO::getNum).reversed()).collect(Collectors.toList());
				}
			}
		}
		return resultList;
	}

	@Override
	public List<CheckStatisticsTrendVO> selectPlanStatusOverdueTrend(SugarSearchDTO searchDTO) {
		String[] initTypeArr = {"计划保养数","已完成保养数","年审梯逾期数","年审梯逾期率"};
		List<CheckStatisticsTrendVO> result = this.initTrendEntirety(searchDTO,initTypeArr);
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<Long> planIds = planContentService.selectElevatorByCollectPlanIds(searchDTO);
		if(Func.isNotEmpty(planIds)){
			List<ElevatorByCollectListDTO> list = planContentService.selectElevatorByCollectList(planIds);
			Map<String,List<ElevatorByCollectListDTO>> dateGroup;
			if(searchDTO.getDataType().equals(1)){
				// 日
				dateGroup = list.stream().collect(Collectors.groupingBy(t -> DateUtil.format(t.getPlanDate(),"yyyy/M/d")));
			}else if(searchDTO.getDataType().equals(2)){
				// 周
				dateGroup = list.stream().collect(Collectors.groupingBy(t -> String.format("%s~%s",DateUtil.format(DateUtil.beginOfWeek(t.getPlanDate()), "yyyy/M/d"), DateUtil.format(DateUtil.endOfWeek(t.getPlanDate()), "yyyy/M/d"))));
			}else {
				// 月
				dateGroup = list.stream().collect(Collectors.groupingBy(t -> String.format("%s月",DateUtil.format(t.getPlanDate(), "yyyy年M"))));
			}
			result.forEach(e -> dateGroup.forEach((k, v) -> {

				// 工单数量
				long planNum;
				BigDecimal numRate;
				if(e.getType().equals(initTypeArr[0])){
					planNum = v.stream().map(ElevatorByCollectListDTO::getPlanId).distinct().count();
					e.getTrendData().put(k,BigDecimal.valueOf(planNum));
				}else if(e.getType().equals(initTypeArr[1])) {
					planNum = v.stream().filter(t -> t.getPlanStatus().equals(TaskStatusEnum.BY_MAINTAIN_SIGN.getStatus()) || t.getPlanStatus().equals(TaskStatusEnum.BY_SIGN.getStatus())).map(ElevatorByCollectListDTO::getPlanId).distinct().count();
					e.getTrendData().put(k,BigDecimal.valueOf(planNum));
				}else if(e.getType().equals(initTypeArr[2])) {
					planNum = v.stream().filter(t -> Func.isNotEmpty(t.getPlanOverdueType()) && Func.isNotEmpty(t.getPlanOverdueType())
						&& t.getPlanAuditType().equals(2) && t.getPlanOverdueType().equals(3)).map(ElevatorByCollectListDTO::getPlanId).distinct().count();
					e.getTrendData().put(k,BigDecimal.valueOf(planNum));
				}else if(e.getType().equals(initTypeArr[3])) {
					long datePlanTotal = v.stream().count();
					long dateOverdue = v.stream().filter(t -> t.getPlanAuditType().equals(2) && Func.isNotEmpty(t.getPlanOverdueType()) && t.getPlanOverdueType().equals(3)).count();
					numRate = BigDecimal.valueOf(dateOverdue).divide(BigDecimal.valueOf(datePlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP);
					e.getTrendData().put(k,numRate);
				}
			}));
		}
		return result;
	}

	@Override
	public List<CheckStatisticsTrendVO> selectPlanZgAppearTrend(SugarSearchDTO searchDTO) {
		String[] initTypeArr = {"需整改保养单数","整改出现率"};
		List<CheckStatisticsTrendVO> result = this.initTrendEntirety(searchDTO,initTypeArr);
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<Long> planIds = planContentService.selectElevatorByCollectPlanIds(searchDTO);
		if(Func.isNotEmpty(planIds)){
			List<ElevatorByCollectListDTO> list = planContentService.selectElevatorByCollectCorrelationZgList(planIds);
			Map<String,List<ElevatorByCollectListDTO>> dateGroup;
			if(searchDTO.getDataType().equals(1)){
				// 日
				dateGroup = list.stream().collect(Collectors.groupingBy(t -> DateUtil.format(t.getPlanDate(),"yyyy/M/d")));
			}else if(searchDTO.getDataType().equals(2)){
				// 周
				dateGroup = list.stream().collect(Collectors.groupingBy(t -> String.format("%s~%s",DateUtil.format(DateUtil.beginOfWeek(t.getPlanDate()), "yyyy/M/d"), DateUtil.format(DateUtil.endOfWeek(t.getPlanDate()), "yyyy/M/d"))));
			}else {
				// 月
				dateGroup = list.stream().collect(Collectors.groupingBy(t -> String.format("%s月",DateUtil.format(t.getPlanDate(), "yyyy年M"))));
			}

			result.forEach(e -> dateGroup.forEach((k, v) -> {

				if(e.getType().equals(initTypeArr[0])){
					long dateScorePlanTotal = v.stream().filter(t -> Func.isNotEmpty(t.getPlanScoreStatus()) && t.getPlanScoreStatus() == 1).map(ElevatorByCollectListDTO::getPlanId).distinct().count();
					long dateScoreZgTotal = v.stream().filter(t -> Func.isNotEmpty(t.getPlanScoreStatus()) && t.getPlanScoreStatus() == 1 && Func.isNotEmpty(t.getZgPlanId())).map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
					if(dateScorePlanTotal > 0){
						e.getTrendData().put(k,BigDecimal.valueOf(dateScoreZgTotal).divide(BigDecimal.valueOf(dateScorePlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
					}
				}else if(e.getType().equals(initTypeArr[1])) {
					long dateScoreZgTotal = v.stream().filter(t -> Func.isNotEmpty(t.getPlanScoreStatus()) && t.getPlanScoreStatus() == 1 && Func.isNotEmpty(t.getZgPlanId())).map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
					e.getTrendData().put(k,BigDecimal.valueOf(dateScoreZgTotal));
				}
			}));
		}
		return result;
	}

	@Override
	public List<CheckStatisticsTrendVO> selectPlanZgStatusTrend(SugarSearchDTO searchDTO) {
		String[] initTypeArr = {"整改完成率","整改按时完成率"};
		List<CheckStatisticsTrendVO> result = this.initTrendEntirety(searchDTO,initTypeArr);
		// 根据传入组别获取本级及以下
		if(Func.isNotEmpty(searchDTO.getDeptIds())){
			searchDTO.setDeptIds(deptService.selectDeptAndAllChildIds(searchDTO.getDeptIds()));
		}
		List<ElevatorByCollectListDTO> list = planContentService.selectElevatorByCollectCorrelationZgStatusList(searchDTO);
		if(Func.isNotEmpty(list)){
			Map<String,List<ElevatorByCollectListDTO>> dateGroup;
			if(searchDTO.getDataType().equals(1)){
				// 日
				dateGroup = list.stream().collect(Collectors.groupingBy(t -> DateUtil.format(t.getZgCreateTime(),"yyyy/M/d")));
			}else if(searchDTO.getDataType().equals(2)){
				// 周
				dateGroup = list.stream().collect(Collectors.groupingBy(t -> String.format("%s~%s",DateUtil.format(DateUtil.beginOfWeek(t.getZgCreateTime()), "yyyy/M/d"), DateUtil.format(DateUtil.endOfWeek(t.getZgCreateTime()), "yyyy/M/d"))));
			}else {
				// 月
				dateGroup = list.stream().collect(Collectors.groupingBy(t -> String.format("%s月",DateUtil.format(t.getZgCreateTime(), "yyyy年M"))));
			}

			result.forEach(e -> dateGroup.forEach((k, v) -> {

				long zgPlanTotal = v.stream().map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
				if(zgPlanTotal > 0){
					if(e.getType().equals(initTypeArr[0])){
						long zgPlanFinshedTotal = v.stream().filter(t -> t.getZgPlanStatus().equals(TaskStatusEnum.ZG_SIGN_FINISH.getStatus())).map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
						e.getTrendData().put(k,BigDecimal.valueOf(zgPlanFinshedTotal).divide(BigDecimal.valueOf(zgPlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
					}else if(e.getType().equals(initTypeArr[1])) {
						long correlationZgOnTime = v.stream().filter(t -> t.getZgPlanStatus().equals(TaskStatusEnum.ZG_SIGN_FINISH.getStatus())
							&& ((Func.isNotEmpty(t.getZgRedeployUserIds()) && t.getZgRedeployOverdueStatus().equals(1))
							|| (Func.isEmpty(t.getZgRedeployUserIds()) && t.getZgOverdueType().equals(1)))).map(ElevatorByCollectListDTO::getZgPlanId).distinct().count();
						e.getTrendData().put(k,BigDecimal.valueOf(correlationZgOnTime).divide(BigDecimal.valueOf(zgPlanTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
					}
				}
			}));
		}
		return result;
	}

	public static void main(String[] args) {
	}

	/**
	 * 初始化保养趋势整体数据
	 * @param searchDTO
	 * @return
	 */
	private Map<String,Object> initTrendEntiretyDay(SugarSearchDTO searchDTO) {
		Map<String,Object> trendData = new LinkedHashMap<>(32);
		// 日
		List<DateTime> rangeDate = DateUtil.rangeToList(searchDTO.getStartDate(), searchDTO.getEndDate(), DateField.DAY_OF_YEAR);
		rangeDate.forEach(date -> {
			trendData.put(DateUtil.format(date, "yyyy/M/d"), BigDecimal.ZERO);
		});
		return trendData;
	}

	/**
	 * 初始化保养趋势整体数据
	 * @param searchDTO
	 * @param initTypeArr
	 * @return
	 */
	private List<CheckStatisticsTrendVO> initTrendEntirety(SugarSearchDTO searchDTO, String[] initTypeArr) {
		List<CheckStatisticsTrendVO> initList = new ArrayList<>();
		for (String initType: initTypeArr) {
			CheckStatisticsTrendVO init = new CheckStatisticsTrendVO();
			init.setType(initType);
			Map<String,Object> trendData = new LinkedHashMap<>(32);
			if(searchDTO.getDataType().equals(1)){
				// 日
				List<DateTime> rangeDate = DateUtil.rangeToList(searchDTO.getStartDate(), searchDTO.getEndDate(), DateField.DAY_OF_YEAR);
				rangeDate.forEach(date -> {
					trendData.put(DateUtil.format(date, "yyyy/M/d"), BigDecimal.ZERO);
				});
			}else if(searchDTO.getDataType().equals(2)){
				// 周
				List<DateTime> rangeDate = DateUtil.rangeToList(searchDTO.getStartDate(), searchDTO.getEndDate(), DateField.DAY_OF_YEAR);
				rangeDate.forEach(date -> {
					String weekDate = String.format("%s~%s",DateUtil.format(DateUtil.beginOfWeek(date), "yyyy/M/d"), DateUtil.format(DateUtil.endOfWeek(date), "yyyy/M/d"));
					if (!trendData.containsKey(weekDate)) {
						trendData.put(weekDate,BigDecimal.ZERO);
					}
				});
			}else {
				// 月
				List<DateTime> rangeDate = DateUtil.rangeToList(searchDTO.getStartDate(),searchDTO.getEndDate(), DateField.MONTH);
				rangeDate.forEach(date -> {
					String monthDate = String.format("%s月",DateUtil.format(date, "yyyy年M"));
					trendData.put(monthDate, BigDecimal.ZERO);
				});
			}
			init.setTrendData(trendData);

			initList.add(init);
		}
		return initList;
	}

}
